#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// MAX_FOLDER_LEN - Folders name will truncated to this length
#define MAX_FOLDER_LEN 14

// HEAD_DEPTH - The number of folders to display in the head
#define HEAD_DEPTH 2

// TAIL_ONLY_THRESHOLD - The threshold that governs the tail only
//   display. If the folder count does not exceed this value the path will
//   in tail only mode regardless of the length of the folders.
//   MUST BE GREATER THAN HEAD_DEPTH.
#define TAIL_ONLY_THRESHOLD 4

// MAX_PATH_DEPTH - If path exceeds this program terminates.
#define MAX_PATH_DEPTH 64

const char PATH_DILIMITOR = '/';
const char ELLIPSIS[3] = {0xE2, 0x80, 0xA6};

/**
 * write_folder - writes the first folder to STDOUT in given folder array
 * @folder: folder array
 *
 * Returns the number of characters written.
 */
unsigned int write_folder(const char **folder){
  unsigned int len = folder[1] - folder[0];
  fwrite(folder[0], sizeof(char),
         len > MAX_FOLDER_LEN ? MAX_FOLDER_LEN : len, stdout);
  if (len > MAX_FOLDER_LEN){
    fwrite(ELLIPSIS, sizeof(char), 3, stdout);
    return MAX_FOLDER_LEN+1;
  }
  return len;
}

/**
 * write_folders - writes folders to STDOUT given folder array
 * @folders: folder array
 * @n: number of folders to write
 *
 * Returns the number of characters written.
 */
unsigned int write_folders(const char **folder, int n){
  int out = 0;
  while(n-- != 0 && **folder) out += write_folder(folder++);
  return out;
}

/**
 * find_tail - find a null terminated folder array within max characters
 * @start: folder array
 * @max: the max amount of characters available to print
 * @len: the length of the folder array start
 *
 * Returns null terminated folder array within max characters
 */
const char **find_tail(const char **start, int max, int len){
  const char **end = start+len;
  while (start != end && (max -= (*end - *(end-1))) > 0) end--;
  return end;
}

/**
 * parse_path - parses file path into array folders
 * @path: the path to parse
 * @folders: array to contain path must at least MAX_PATH_DEPTH in length
 *
 * Returns the length folders array
 */
int parse_path(const char *path, const char **folders){
  int cnt = 0;
  if (*path != PATH_DILIMITOR) folders[cnt++] = path;
  do {
    if (*path != PATH_DILIMITOR) continue;
    if (cnt >= MAX_PATH_DEPTH) return MAX_PATH_DEPTH;
    folders[cnt++] = path;
  } while (*(++path));
  folders[cnt] = path;
  return cnt;
}

int main(int argc, char *argv[]){
  int maxlen;
  if (argc < 3 || (maxlen = atoi(argv[1])) <= 0){
    printf("Usage: %s max_length path\n", argv[0]);
    printf("Examples: %s 33 '/varlongpathname/exam/folder/doc/cat'\n", argv[0]);
    printf("          %s $COLUMNS $(dirs)\n", argv[0]);
    return 0;
  };
  const char *folders[MAX_PATH_DEPTH + 1];

  int cnt = parse_path(argv[2], folders);

  const char **tail = NULL;
  if (cnt < TAIL_ONLY_THRESHOLD){     // Print From Tail Only
    tail = folders;
  } else if (maxlen > 30){            // Print From Split View
    maxlen -= write_folders(folders, HEAD_DEPTH);
    if (*(tail = find_tail(&folders[HEAD_DEPTH], maxlen, cnt - HEAD_DEPTH))
        != folders[HEAD_DEPTH]){
      fwrite(&PATH_DILIMITOR, sizeof(char), 1, stdout);
      fwrite(ELLIPSIS, sizeof(char), 3, stdout);
    }
  } else{                              // Print From Head Only
    if ((tail = find_tail(folders, maxlen, cnt)) != folders){
      fwrite(ELLIPSIS, sizeof(char), 3, stdout);
    }
  }
  write_folders(tail,-1);
  fflush(stdout);
}

